package com.inf.utils;

import com.inf.vo.ParamsEsQueryVo;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.*;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by zhangbn on 2018/12/14.
 * 参考博客：https://blog.csdn.net/HoloLens/article/details/79594583
 */
public class EsUtil {

    static Logger log = LoggerFactory.getLogger(EsUtil.class);

    private static final String HOST = "10.82.27.22";
    private static final int PORT = 9201;
    private static final String SCHEMA = "http";
    private static final int MAX_RETRY_TIME_OUT = 60000;
    private static final int CONNECT_TIME_OUT = 5000;
    private static final int SOCKET_TIME_OUT = 60000;
    private static final int CONNECTION_REQUEST_TIME_OUT = 30000;

    private static final int MAX_CONNECT_NUM = 100;
    private static final int MAX_CONNECT_PER_ROUTE = 100;

    private static HttpHost HTTP_HOST = new HttpHost(HOST, PORT, SCHEMA);
    private static boolean uniqueConnectTimeConfig = true;
    private static boolean uniqueConnectNumConfig = true;
    private static boolean isAuth = false;
    private static RestClientBuilder builder;
    private static RestClient restClient;
    private static RestHighLevelClient restHighLevelClient;

    static {
        init();
    }

    private static void init() {
        builder = RestClient.builder(HTTP_HOST);
        builder.setMaxRetryTimeoutMillis(MAX_RETRY_TIME_OUT);
        if (uniqueConnectTimeConfig) {
            setConnectTimeOutConfig();
        }
        if (uniqueConnectNumConfig) {
            setMutiConnectConfig();
        }
        //restClient = builder.build();
        restHighLevelClient = new RestHighLevelClient(builder);
        restClient = restHighLevelClient.getLowLevelClient();
    }

    // 关于异步httpclient的连接延时配置
    private static void setConnectTimeOutConfig() {
        builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {

            @Override
            public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                requestConfigBuilder.setConnectTimeout(CONNECT_TIME_OUT);
                requestConfigBuilder.setSocketTimeout(SOCKET_TIME_OUT);
                requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIME_OUT);
                return requestConfigBuilder;
            }
        });
    }

    // 关于异步httpclient的连接数配置
    private static void setMutiConnectConfig() {
        if (isAuth) {
            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme"));

            builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    httpClientBuilder.setMaxConnTotal(MAX_CONNECT_NUM);
                    httpClientBuilder.setMaxConnPerRoute(MAX_CONNECT_PER_ROUTE);
                    return httpClientBuilder;
                }
            });
        } else {
            builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                    httpClientBuilder.setMaxConnTotal(MAX_CONNECT_NUM);
                    httpClientBuilder.setMaxConnPerRoute(MAX_CONNECT_PER_ROUTE);
                    return httpClientBuilder;
                }
            });
        }

    }

    public static RestClient getClient() {
        return restClient;
    }

    public static RestHighLevelClient getHighLevelClient() {
        return restHighLevelClient;
    }


    public static Response query(String queryString) throws IOException {
        String method = "POST";
        String endpoint = "/brsface/passinfo/_search";
        HttpEntity entity = new NStringEntity(queryString, ContentType.APPLICATION_JSON);
        Request request = new Request(method, endpoint);
        request.setEntity(entity);
        Response response = restClient.performRequest(request);
        log.info("show: response.getEntity()=" + EntityUtils.toString(response.getEntity()));
        return response;
    }

    public static SearchResponse highLevelQuery(ParamsEsQueryVo esQueryVo) throws IOException {
        String index = "brsface";
        String type = "passinfo";
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("pass_id", "180722000016472cbc481614ff584463");
        sourceBuilder.query(termQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        List<String> docIds = new ArrayList<>(hits.getHits().length);
        for (SearchHit hit : hits) {
            docIds.add(hit.getId());
            log.info(hit.getId());
            log.info("show: hit.getSourceAsString()=" + hit.getSourceAsString());
        }
        return response;
    }

    public static void close() {
        if (restClient != null) {
            try {
                //restClient.close();
                restHighLevelClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) throws IOException {


//        String queryString = "{\"query\":{\"bool\":{\"must\":[{\"term\":{\"pass_time\":\"2018-07-21 23:53:36\"}}],\"must_not\":[],\"should\":[]}},\"from\":0,\"size\":10,\"sort\":[],\"aggs\":{}}";
//        Response response = EsUtil.query(queryString);
//        ParamsEsQueryVo esQueryVO = new ParamsEsQueryVo();
//        EsUtil.highLevelQuery(esQueryVO);
//        EsUtil.close();

        System.out.println(Runtime.getRuntime().availableProcessors());


    }

}
